home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CU Amiga Super CD-ROM 17
/
CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso
/
CUCD
/
Programming
/
DiceSource
/
src
/
dc1
/
asubs.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-09-09
|
16KB
|
801 lines
/*
* (c)Copyright 1992-1997 Obvious Implementations Corp. Redistribution and
* use is allowed under the terms of the DICE-LICENSE FILE,
* DICE-LICENSE.TXT.
*/
/*
* ASUBS.C
*
*/
/*
** $Filename: asubs.c $
** $Author: dice $
** $Revision: 30.326 $
** $Date: 1995/12/24 06:09:36 $
** $Log: asubs.c,v $
* Revision 30.326 1995/12/24 06:09:36 dice
* .
*
* Revision 30.5 1994/06/13 18:37:23 dice
* byte ordering portability
*
* Revision 30.0 1994/06/10 18:04:46 dice
* .
*
* Revision 1.3 1993/11/22 00:28:36 jtoebes
* Final cleanup to eliminate all cerror() messages with strings.
*
* Revision 1.2 1993/09/06 13:17:17 jtoebes
* Fixed BUG01091 - Bad error for undefined structure tag.
* Eliminated message because it is now caught in the front end parsing
* routines for structures/unions/arrays.
*
**/
#include "defs.h"
#include "asm.h"
Prototype char SizC[];
Prototype char StorBuf[2][1024];
char SizC[] = { '0', 'b', 'w', '0', 'l', '?' };
char StorBuf[2][1024];
Prototype char *RegMaskToString(long, short *);
Prototype char *StorToString(Stor *, short *);
Prototype char *StorToStringBuf(Stor *, char *);
Prototype long SameStorage(Stor *, Stor *);
Prototype long SameRegister(Stor *, Stor *);
Prototype long RegisterMaskConflict(Stor *, ulong);
Prototype long ImmStorage(Stor *);
Prototype void outop(char *, short, Stor *, Stor *);
Prototype void GenStaticData(Var *);
Prototype void GenDataElm(Exp *, Type *);
Prototype char *itohex(char *, ulong);
Prototype char *itodec(char *, ulong);
Prototype void AutoAggregateBeg(Stor *, Type *);
Prototype void AutoAggregate(void *, long);
Prototype void AutoAggregateEnd(void);
Prototype void AutoAggregateSync(void);
char *
RegMaskToString(mask, pcnt)
long mask;
short *pcnt;
{
static char buf[128];
short i;
short c = 0;
char *ptr = buf;
for (i = 0; i < 32; ++i) {
if (mask & (1 << i)) {
if (c++)
*ptr++ = '/';
if (i < RB_ADDR) {
*ptr++ = 'D';
*ptr++ = i + '0';
} else {
*ptr++ = 'A';
*ptr++ = i + ('0' - RB_ADDR);
}
}
}
*pcnt = c;
*ptr = 0;
return(buf);
}
char *
StorToString(s, plen)
Stor *s;
short *plen;
{
static char *Ptr = StorBuf[0];
char *res;
Ptr = ((Ptr == StorBuf[0]) ? StorBuf[1] : StorBuf[0]);
res = StorToStringBuf(s, Ptr);
if (plen)
*plen = res - Ptr;
return(Ptr);
}
char *
StorToStringBuf(s, base)
Stor *s;
char *base;
{
char *t = base;
switch(s->st_Type) {
case ST_PtrConst:
*t = '$';
t = itohex(t + 1, s->st_PtrConst);
if ((long)s->st_PtrConst >= -32768 && (long)s->st_PtrConst < 32768) {
*t = '.'; ++t;
*t = 'W'; ++t;
}
break;
case ST_IntConst: /* complication is for pretty output */
*t = '#'; ++t;
if (s->st_IntConst < 0) {
*t = '-'; ++t;
*t = '$'; ++t;
t = itohex(t, -s->st_IntConst);
} else {
*t = '$'; ++t;
t = itohex(t, s->st_IntConst);
}
break;
case ST_FltConst:
t += sprintf(t, "<flt-const>");
break;
case ST_StrConst:
dbprintf(("asm-gen, string constant not turned into label"));
Assert(0);
t += sprintf(t, "<str-const>");
break;
case ST_Reg:
if (s->st_RegNo < RB_ADDR) {
*t = 'D'; ++t;
if (s->st_RegNo < 10) {
*t = s->st_RegNo + '0';
++t;
} else {
t[0] = '1';
t[1] = s->st_RegNo + ('0' - 10);
t += 2;
}
} else {
*t = 'A'; ++t;
if (s->st_RegNo < RB_ADDR + 10) {
*t = s->st_RegNo + ('0' - RB_ADDR);
++t;
} else {
t[0] = '1';
t[1] = s->st_RegNo + ('0' - 10 - RB_ADDR);
t += 2;
}
}
break;
case ST_RelArg:
{
long offset = s->st_Offset;
*t = 'l'; ++t;
t = itodec(t, LabelRegsUsed);
/*
* If procedure returns a structure take into account arguments
*/
switch(ProcVar->Type->SubType->Id) {
case TID_STRUCT:
case TID_UNION:
offset += 4;
break;
}
if (s->st_RegNo == RB_SP)
offset -= 4;
if (offset >= 0) {
*t = '+';
++t;
}
t = itodec(t, offset);
*t = '('; ++t;
*t = 'A'; ++t;
if (s->st_RegNo < RB_ADDR + 10) {
*t = s->st_RegNo + ('0' - RB_ADDR);
++t;
} else {
t[0] = '1';
t[1] = s->st_RegNo + ('0' - RB_ADDR - 10);
t += 2;
}
*t = ')'; ++t;
}
break;
case ST_RelReg:
if (s->st_RegNo < RB_ADDR)
{
dbprintf(("asubs: rel(Dn) request! ??"));
Assert(0);
}
if (s->st_Offset)
t = itodec(t, s->st_Offset);
*t = '('; ++t;
*t = 'A'; ++t;
if (s->st_RegNo < RB_ADDR + 10) {
*t = s->st_RegNo + ('0' - RB_ADDR);
++t;
} else {
t[0] = '1';
t[1] = s->st_RegNo + ('0' - RB_ADDR - 10);
t += 2;
}
*t = ')'; ++t;
break;
case ST_RegIndex: /* offset(An,Dn.[W/L]) */
if (s->st_Offset) {
t = itodec(t, s->st_Offset);
} else {
*t = '0';
++t;
}
*t = '('; ++t;
*t = 'A'; ++t;
if (s->st_RegNo < RB_ADDR + 10) {
*t = s->st_RegNo + ('0' - RB_ADDR);
++t;
} else {
t[0] = '1';
t[1] = s->st_RegNo + ('0' - RB_ADDR - 10);
t += 2;
}
*t = ','; ++t;
if (s->st_RegNo2 >= RB_ADDR) {
t[0] = 'A';
t[1] = s->st_RegNo2 + ('0' - RB_ADDR);
} else {
t[0] = 'D';
t[1] = s->st_RegNo2 + '0';
}
t += 2;
*t = '.'; ++t;
if (s->st_Flags & SF_IDXWORD)
*t = 'W';
else
*t = 'L';
++t;
if (s->st_Flags & (SF_IDXSCAL2|SF_IDXSCAL4|SF_IDXSCAL8)) {
*t = '*'; ++t;
if (s->st_Flags & SF_IDXSCAL2)
*t = '2';
else if (s->st_Flags & SF_IDXSCAL4)
*t = '4';
else
*t = '8';
++t;
}
*t = ')'; ++t;
break;
case ST_RelLabel:
if (s->st_Flags & SF_REGARGS) {
*t = '@';
++t;
}
*t = 'l'; ++t;
t = itodec(t, s->st_Label);
if (s->st_Offset) {
if (s->st_Offset >= 0) {
*t = '+';
++t;
}
t = itodec(t, s->st_Offset);
}
if (s->st_Flags & SF_CODE) {
if ((SmallCode || (s->st_Flags & SF_NEAR)) && !(s->st_Flags & SF_FAR)) {
*t = '('; ++t;
*t = 'p'; ++t;
*t = 'c'; ++t;
*t = ')'; ++t;
}
} else {
if ((SmallData || (s->st_Flags & SF_NEAR)) && !(s->st_Flags & SF_FAR)) {
if (SmallData == 2) {
*t = '.'; ++t;
*t = 'W'; ++t;
} else {
*t = '('; ++t;
*t = 'A'; ++t;
*t = '4'; ++t;
*t = ')'; ++t;
}
}
}
break;
case ST_RelName:
if (s->st_Flags & SF_REGARGS)
*t = '@';
else
*t = '_';
++t;
movmem(s->st_Name->Name, t, s->st_Name->Len);
t += s->st_Name->Len;
if (s->st_Offset) {
if (s->st_Offset >= 0) {
*t = '+';
++t;
}
t = itodec(t, s->st_Offset);
}
if (s->st_Flags & SF_CODE) {
if ((SmallCode || (s->st_Flags & SF_NEAR)) && !(s->st_Flags & SF_FAR)) {
*t = '('; ++t;
*t = 'p'; ++t;
*t = 'c'; ++t;
*t = ')'; ++t;
}
} else {
if ((SmallData || (s->st_Flags & SF_NEAR)) && !(s->st_Flags & SF_FAR)) {
if (SmallData == 2) {
*t = '.'; ++t;
*t = 'W'; ++t;
} else {
*t = '('; ++t;
*t = 'A'; ++t;
*t = '4'; ++t;
*t = ')'; ++t;
}
}
}
break;
case ST_Push:
*t = '-'; ++t;
*t = '('; ++t;
*t = 's'; ++t;
*t = 'p'; ++t;
*t = ')'; ++t;
break;
default:
t += sprintf(t, "?%d", s->st_Type);
break;
}
*t = 0;
return(t);
}
/*
* Same physical storage, possibly different sizes
*/
long
SameStorage(s1, s2)
Stor *s1, *s2;
{
if ((s1->st_Flags ^ s2->st_Flags) & SF_LEA)
return(0);
if (s1->st_Type != s2->st_Type)
return(0);
if (s1->st_Type == ST_Reg)
return(s1->st_RegNo == s2->st_RegNo);
switch(s1->st_Type) {
case ST_PtrConst:
return(s1->st_PtrConst == s2->st_PtrConst);
case ST_IntConst:
return(s1->st_IntConst == s2->st_IntConst);
case ST_FltConst:
return(s1->st_FltConst == s2->st_FltConst);
case ST_StrConst:
return(s1->st_StrConst == s2->st_StrConst);
case ST_RelArg:
return(s1->st_Offset == s2->st_Offset);
case ST_RelReg:
return(s1->st_RegNo == s2->st_RegNo && s1->st_Offset == s2->st_Offset);
case ST_RelLabel:
return(s1->st_Label == s2->st_Label && s1->st_Offset == s2->st_Offset);
case ST_RelName:
return(s1->st_Name == s2->st_Name && s1->st_Offset == s2->st_Offset);
case ST_RegIndex:
return(s1->st_RegNo == s2->st_RegNo && s1->st_Offset == s2->st_Offset && s1->st_RegNo2 == s2->st_RegNo2);
default:
dbprintf(("Bad storage type for same-compare %d\n", s1->st_Type));
}
Assert(0);
return(0); /* not reached */
}
/*
* Will the registers used in one storage structure interfere with the
* registers used in another?
*/
long
SameRegister(s1, s2)
Stor *s1, *s2;
{
switch(s1->st_Type) {
case ST_Reg:
case ST_RelReg:
switch(s2->st_Type) {
case ST_Reg:
case ST_RelReg:
if (s1->st_RegNo == s2->st_RegNo)
return(1);
break;
case ST_RegIndex:
if (s1->st_RegNo == s2->st_RegNo || s1->st_RegNo == s2->st_RegNo2)
return(1);
break;
}
break;
case ST_RegIndex:
switch(s2->st_Type) {
case ST_Reg:
case ST_RelReg:
if (s2->st_RegNo == s1->st_RegNo || s2->st_RegNo == s1->st_RegNo2)
return(1);
break;
case ST_RegIndex:
if (s2->st_RegNo == s1->st_RegNo || s2->st_RegNo == s1->st_RegNo2 || s2->st_RegNo2 == s1->st_RegNo || s2->st_RegNo2 == s1->st_RegNo2)
return(1);
break;
}
break;
}
return(0);
}
long
RegisterMaskConflict(s1, mask)
Stor *s1;
ulong mask;
{
switch(s1->st_Type) {
case ST_Reg:
case ST_RelReg:
if ((1 << s1->st_RegNo) & mask)
return(1);
break;
case ST_RegIndex:
if (((1 << s1->st_RegNo) | (1 << s1->st_RegNo2)) & mask)
return(1);
break;
case ST_RelName:
case ST_RelLabel:
if ((s1->st_Flags & (SF_FAR|SF_CODE)) == 0 && (mask & RF_A4))
return(1);
break;
case ST_RelArg:
if (mask & RF_A5)
return(1);
break;
}
return(0);
}
/*
* Does the storage represent some sort of immediate value? This includes
* effective addresses
*/
long
ImmStorage(stor)
Stor *stor;
{
if (stor->st_Type == ST_IntConst || stor->st_Type == ST_PtrConst)
return(1);
if ((stor->st_Flags & SF_LEA) && (stor->st_Type == ST_RelLabel || stor->st_Type == ST_RelName))
return(1);
return(0);
}
void
outop(char *op, short siz, Stor *s, Stor *d)
{
char *ptr = StorBuf[0];
if (siz == 0)
siz = d->st_Size;
if (siz > 4)
siz = 5;
*ptr = '\t'; ++ptr;
while ((*ptr = *op) != 0) {
++ptr;
++op;
}
if (siz >= 0) {
*ptr = '.'; ++ptr;
*ptr = SizC[siz]; ++ptr;
}
*ptr = '\t'; ++ptr;
if (s) {
ptr = StorToStringBuf(s, ptr);
*ptr = ','; ++ptr;
}
ptr = StorToStringBuf(d, ptr);
*ptr = '\n'; ++ptr;
fwrite(StorBuf[0], ptr - StorBuf[0], 1, stdout);
}
/*
* Generate structured static/global data.
*
* If the resident (-r) option is used we cannot generate data-data
* relocations ... we must do them in an autoinit section using A4
* relative addressing.
*
* Most of the structural considerations are handled by GenBracedEq/Assign
* which is forced for static/global initialization.
*/
void
GenStaticData(var)
Var *var;
{
if ((var->Flags & TF_ALIGNED) || var->Type->Align == 4)
printf("\tds.l\t0\n");
else if (var->Type->Align != 1)
printf("\tds.w\t0\n");
if (var->var_Stor.st_Type == ST_RelName)
printf("_%s", SymToString(var->var_Stor.st_Name));
else
printf("l%ld", var->var_Stor.st_Label);
if (var->u.AssExp == NULL) {
printf("\tds.b\t%ld\n", var->Type->Size);
} else {
/*
* Generate the data from the expression.
*/
puts("");
GenDataElm(var->u.AssExp, var->Type);
}
OutAlign = var->Type->Size & 3;
/*
* If a __config variable then generate an autoconfig section for
* it.
*/
if (var->Flags & TF_CONFIG) {
printf("\tsection\tautoconfig,code\n");
printf("\tpea\t%s\n", StorToString(&var->var_Stor, NULL));
if (var->var_Stor.st_Size < 32768)
printf("\tpea\t%ld.W\n", var->var_Stor.st_Size);
else
printf("\tpea\t%ld\n", var->var_Stor.st_Size);
if (SmallCode || PIOpt)
printf("\tjsr\t__DiceConfig(pc)\n");
else
printf("\tjsr\t__DiceConfig\n");
AddAuxSub("DiceConfig");
puts(LastSectBuf);
}
}
/*
* GegnDataElm()
*
* run through element generation for expression, which MUST be of type
* TokExpAssBlock
*/
void
GenDataElm(exp, type)
Exp *exp;
Type *type;
{
short savePass = GenPass;
Assert(exp->ex_Token == TokExpAssBlock);
Assert(exp->ex_Type == type);
/*
* Run through expression generation passes
*/
GenGlobal = 1;
GenPass = 0;
(*exp->ex_Func)(&exp);
GenPass = 1;
AutoAggregateBeg(NULL, exp->ex_Type);
(*exp->ex_Func)(&exp);
AutoAggregateEnd();
GenPass = savePass;
GenGlobal = 0;
}
char *
itohex(ptr, val)
char *ptr;
ulong val;
{
static char HA[] = { "0123456789ABCDEF" };
short dig = 8;
char *p;
if (val < 0x10000) {
dig = 4;
if (val < 0x100)
dig = 2;
}
ptr += dig;
p = ptr;
*p-- = 0;
while (dig--) {
*p-- = HA[(short)val & 0xF];
val >>= 4;
}
return(ptr);
}
char *
itodec(ptr, val)
char *ptr;
ulong val;
{
if ((long)val < 0) {
val = -val;
*ptr++ = '-';
}
if (val < 10) {
*ptr++ = '0' + val;
} else if (val < 100) {
*ptr++ = '0' + val / 10;
*ptr++ = '0' + val % 10;
} else {
char buf[16];
short i = 15;
while (val > 32767) {
buf[i--] = '0' + val % 10;
val /= 10;
}
while (val) {
buf[i--] = '0' + (uword)val % (uword)10;
val = (short)val / (short)10;
}
while (i != 15)
*ptr++ = buf[++i];
}
*ptr = 0;
return(ptr);
}
static long AGLabel;
static long AGIndex;
static TmpAggregate *AGBase;
static TmpAggregate **AGNext;
void
AutoAggregateBeg(s, type)
Stor *s;
Type *type;
{
AGLabel = AllocLabel();
AGBase = NULL;
AGNext = &AGBase;
if (GenGlobal == 0) {
setmem(s, sizeof(Stor), 0);
s->st_Type = ST_RelLabel;
s->st_Offset = 0;
s->st_Size = type->Size;
s->st_Label = AGLabel;
s->st_Flags = (SmallData) ? SF_NEAR : SF_FAR;
}
}
void
AutoAggregate(ptr, n)
void *ptr;
long n;
{
TmpAggregate *ag = *AGNext;
if (ag == NULL || ag->ta_Bytes - ag->ta_Index < n) {
long v = (n > 512) ? n : 512;
if (ag)
AGNext = &ag->ta_Next;
ag = malloc(sizeof(TmpAggregate) + v);
if (ag == NULL)
NoMem();
ag->ta_Next = NULL;
ag->ta_Buf = (char *)(ag + 1);
ag->ta_Index = 0;
ag->ta_Bytes = v;
*AGNext = ag;
}
{
char *dptr = ag->ta_Buf + ag->ta_Index;
if (ptr)
movmem(ptr, dptr, n);
else
setmem(dptr, n, 0);
}
ag->ta_Index += n;
}
void
AutoAggregateSync()
{
TmpAggregate *ag, *agNext;
if (GenGlobal == 0 && AGLabel) {
asm_segment(&DummyDataVar);
printf("\tds.l\t0\n");
printf("l%ld\n", AGLabel);
AGLabel = 0;
}
for (ag = AGBase; ag; ag = agNext) {
long i;
short col = 0;
agNext = ag->ta_Next;
if ((AGIndex & 3) == 0 && (ag->ta_Index & 3) == 0) {
for (i = 0; i < ag->ta_Index; i += 4) {
if (col == 0) {
printf("\n\tdc.l\t");
} else {
putc(',', stdout);
++col;
}
col += printf("$%lx", ToMsbOrder(*(unsigned long *)(ag->ta_Buf + i)));
if (col > 120)
col = 0;
}
} else if ((AGIndex & 1) == 0 && (ag->ta_Index & 1) == 0) {
for (i = 0; i < ag->ta_Index; i += 2) {
if (col == 0) {
printf("\n\tdc.w\t");
} else {
putc(',', stdout);
++col;
}
col += printf("$%lx", ToMsbOrderShort(*(unsigned short *)(ag->ta_Buf + i)));
if (col > 120)
col = 0;
}
} else {
for (i = 0; i < ag->ta_Index; i += 1) {
if (col == 0) {
printf("\n\tdc.b\t");
} else {
putc(',', stdout);
++col;
}
col += printf("$%lx", (unsigned long)*(unsigned char *)(ag->ta_Buf + i));
if (col > 120)
col = 0;
}
}
AGIndex += ag->ta_Index;
puts("");
free(ag);
}
AGBase = NULL;
AGNext = &AGBase;
}
void
AutoAggregateEnd()
{
if (GenGlobal == 0 && AGLabel) {
asm_segment(&DummyDataVar);
printf("\tds.l\t0\n");
printf("l%ld\n", AGLabel);
AGLabel = 0;
}
AutoAggregateSync();
puts("");
if (GenGlobal == 0) {
asm_segment(&DummyCodeVar);
}
}